#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
bool getNextValue1(const char* strExpress, int& nBegin, int& nEnd, double& dValue) 
{
	int i;
	bool bHasDot = false;
	for (i=nBegin;i<nEnd;i++)
	{
		if (strExpress[i] == '.')
		{
			if (bHasDot)
			{
				break;
			}
			bHasDot = true;
			continue;
		}
		if(strExpress[i] > '9' || strExpress[i] < '0')
			break;
	}
	nEnd = i;
	if (nEnd <= nBegin)
	{
		return false;
	}
	// 	char* p = (char*)malloc(nEnd - nBegin + 2);
	// 	memset(p, 0, nEnd - nBegin + 2);
	// 	strncpy(p, strExpress + nBegin, nEnd - nBegin);
	if (bHasDot)
	{
		float fValue;
		sscanf(strExpress + nBegin, "%f", &fValue);
		dValue = fValue;
	} 
	else 
	{
		int nValue;
		sscanf(strExpress + nBegin, "%d", &nValue);
		dValue = nValue;
	}
	return true;
}

char getNextOp1(const char* strExpress, int& nBegin, int& nEnd)
{
	for (int i=nBegin;i<nEnd;i++)
	{
		if (strExpress[i] == ' ')
		{
			continue;
		}
		if ('(' == strExpress[i] || ')' == strExpress[i] || strExpress[i] == '+' || strExpress[i] == '-' || strExpress[i] == '*' || strExpress[i] == '/')
		{
			nEnd = i + 1;
			return strExpress[i];
		}
		nEnd = i;
		break;
	}
	return 0;
}
bool calc1(const char* strExpress, int nBegin, int nEnd, double& dResult)
{
	int nOpEnd = nEnd;
	if (nBegin >= nEnd)
	{
		return false;
	}
	char cOp = getNextOp1(strExpress, nBegin, nOpEnd);
	int nOp1Begin = nOpEnd;
	int nOp1End = nEnd;
	char cOp1 = getNextOp1(strExpress, nOp1Begin, nOp1End);
	
	if (cOp == '*' || cOp == '/' || cOp == 0)
	{
		int nTmpBegin1 = nOpEnd;
		int nTmpEnd1 = nEnd;
		double dValue = 0;
		if (cOp != 0 && cOp1 == '(') {
			int nCount=1;
			int nTmpBegin1 = nOp1End;
			for (;nCount > 0 && nTmpBegin1 < nEnd;nTmpBegin1++)
			{
				if (strExpress[nTmpBegin1] == '(')
				{
					nCount++;
				}
				else if(strExpress[nTmpBegin1] == ')')
				{
					nCount--;
				}
			}
			if (!calc1(strExpress, nOp1End, nTmpBegin1, dValue))
			{
				return false;
			}
			char cOp1 = getNextOp1(strExpress, nTmpBegin1, nTmpEnd1);
		}
		else if (!getNextValue1(strExpress, nTmpBegin1, nTmpEnd1, dValue))
		{
			return false;
		}
		if (cOp == '*')
			dResult *= dValue;
		else if (cOp == '/')
			dResult /= dValue;
		else if (cOp == 0)
			dResult += dValue;
		int nTmpBegin2 = nTmpEnd1;
		int nTmpEnd2 = nEnd;
		char cNextOp = getNextOp1(strExpress, nTmpBegin2, nTmpEnd2);
		if (cNextOp != 0)
		{
			return calc1(strExpress, nTmpEnd1, nEnd, dResult);;
		}
		return true;
	} else if (cOp == '+' || cOp == '-') {
		int nTmpBegin1 = nOpEnd;
		int nTmpEnd1 = nEnd;
		double dValue = 0;
		if (cOp != 0 && cOp1 == '(') {
			int nCount=1;
			int nTmpBegin1 = nOp1End;
			for (;nCount > 0 && nTmpBegin1 < nEnd;nTmpBegin1++)
			{
				if (strExpress[nTmpBegin1] == '(')
				{
					nCount++;
				}
				else if(strExpress[nTmpBegin1] == ')')
				{
					nCount--;
				}
			}
			if (!calc1(strExpress, nOp1End, nTmpBegin1, dValue))
			{
				return false;
			}
			nTmpEnd1 = nTmpBegin1;
		}
		else if (nTmpBegin1 >= nTmpEnd1 || !getNextValue1(strExpress, nTmpBegin1, nTmpEnd1, dValue))
		{
			return false;
		}
		int nTmpBegin2 = nTmpEnd1;
		int nTmpEnd2 = nEnd;
		char cNextOp = getNextOp1(strExpress, nTmpBegin2, nTmpEnd2);
		if (cNextOp == '*' || cNextOp == '/')
		{
			int nLoopBegin = nOpEnd;
			int nLoopEnd = nEnd;
			double dTmpValue = 0;
			bool bHasFlag = false;
			if (strExpress[nLoopBegin] == '(') {
				int nCount=1;
				int nTmpBegin5 = nLoopBegin + 1;
				for (;nCount > 0 && nTmpBegin5 < nEnd;nTmpBegin5++)
				{
					if (strExpress[nTmpBegin5] == '(')
					{
						nCount++;
					}
					else if(strExpress[nTmpBegin5] == ')')
					{
						nCount--;
					}
				}
				nLoopEnd = nTmpBegin5;
				bHasFlag = true;
			}
			do 
			{
				if(!bHasFlag && !getNextValue1(strExpress, nLoopBegin, nLoopEnd, dTmpValue))
					return false;
				nLoopBegin = nLoopEnd;
				nLoopEnd = nEnd;
				if (nLoopBegin >= nLoopEnd)
				{
					break;
				}
				char cTmpOp = getNextOp1(strExpress, nLoopBegin, nLoopEnd);
				if (cTmpOp != '*' && cTmpOp != '/')
				{
					break;
				}
				nLoopBegin = nLoopEnd;
				nLoopEnd = nEnd;
				bHasFlag = false;
			} while (true);

			if (!calc1(strExpress, nTmpEnd1, nLoopBegin, dValue))
			{
				return false;
			}
			nTmpEnd1 = nLoopBegin;
		}
		if (cOp == '+')
		{
			dResult += dValue;
		}
		else if (cOp == '-')
		{
			dResult -= dValue;
		}
		return calc1(strExpress, nTmpEnd1, nEnd, dResult);

	} 
	else if (cOp == ')')
	{
		return true;
	}
	return false;
}

int main()
{
	double dResult = 0;
	char *expStr = "1+(0.5*2+3.5+4*2.5-2)/2";
	int nBegin = 0;
	int nEnd = strlen(expStr);
	bool bRet = calc1(expStr, nBegin, nEnd, dResult);
	printf("calc return %d Result=%f check=%f", bRet, dResult, (double)1+((double)0.5*2+(double)3.5+(double)4*(double)2.5-(double)2)/(double)2);


}